#!/usr/bin/env python
# -*- coding: utf-8 -*-

import asyncio
import threading
import tempfile
import time
import logging
from pathlib import Path
from typing import Dict, Optional, Any, Type
from dataclasses import dataclass, field
from datetime import datetime

from .base_converter import BaseConverter
from .pdf_converter import PDFConverter
from .docx_converter import DOCXConverter
from .ppt_converter import PPTConverter
from .image_converter import ImageConverter
from .work_dir_config import work_dir_config

logger = logging.getLogger(__name__)

@dataclass
class ConverterInstance:
    """转换器实例信息"""
    converter: BaseConverter
    created_time: datetime
    last_used_time: datetime
    use_count: int = 0
    temp_dir: Optional[Path] = field(default=None)

class ConverterManager:
    """转换器管理器 - 单例模式管理所有转换器实例"""
    
    _instance = None
    _lock = threading.Lock()
    _debug_mode = False  # 添加内部调试模式标记
    
    def __new__(cls):
        if cls._instance is None:
            with cls._lock:
                if cls._instance is None:
                    cls._instance = super().__new__(cls)
                    cls._instance._initialized = False
        return cls._instance
    
    def __init__(self):
        if self._initialized:
            return
            
        self._initialized = True
        self._instances: Dict[str, ConverterInstance] = {}
        self._instance_locks: Dict[str, threading.Lock] = {}
        self._global_lock = threading.Lock()
        
        # 转换器类映射
        self._converter_classes = {
            'pdf': PDFConverter,
            'docx': DOCXConverter,
            'ppt': PPTConverter,
            'image': ImageConverter
        }
        
        # 文件扩展名到转换器类型的映射
        self._ext_to_converter = {
            '.pdf': 'pdf',
            '.docx': 'docx',
            '.doc': 'docx',
            '.pptx': 'ppt',
            '.ppt': 'ppt',
            '.png': 'image',
            '.jpg': 'image',
            '.jpeg': 'image',
            '.gif': 'image',
            '.bmp': 'image',
            '.tiff': 'image',
            '.webp': 'image'
        }
        
        # 同步调试模式状态
        self._sync_debug_mode()
        
        logger.info("转换器管理器已初始化")
    
    def _sync_debug_mode(self):
        """同步调试模式状态"""
        try:
            from .work_dir_config import work_dir_config
            self._debug_mode = getattr(work_dir_config, '_debug_mode', False)
        except:
            self._debug_mode = False
    
    def set_debug_mode(self, debug_mode: bool):
        """设置调试模式"""
        self._debug_mode = debug_mode
        logger.info(f"转换器管理器调试模式设置为: {debug_mode}")
    
    def get_converter_type(self, file_path: Path) -> Optional[str]:
        """根据文件扩展名获取转换器类型"""
        ext = file_path.suffix.lower()
        return self._ext_to_converter.get(ext)
    
    def get_converter(self, converter_type: str, method: Optional[str] = None, file_id: Optional[str] = None) -> BaseConverter:
        """
        获取转换器实例（单例模式）
        
        Args:
            converter_type: 转换器类型 ('pdf', 'docx', 'ppt', 'image')
            method: 转换方法（可选）
            file_id: 文件ID（可选），用于创建专用工作目录
            
        Returns:
            BaseConverter: 转换器实例
        """
        # 创建实例标识符
        instance_key = f"{converter_type}_{method or 'default'}"
        
        # 如果实例已存在，直接返回
        if instance_key in self._instances:
            instance = self._instances[instance_key]
            instance.last_used_time = datetime.now()
            instance.use_count += 1
            logger.debug(f"重用转换器实例: {instance_key} (使用次数: {instance.use_count})")
            return instance.converter
        
        # 创建新实例（线程安全）
        if instance_key not in self._instance_locks:
            with self._global_lock:
                if instance_key not in self._instance_locks:
                    self._instance_locks[instance_key] = threading.Lock()
        
        with self._instance_locks[instance_key]:
            # 双重检查
            if instance_key in self._instances:
                instance = self._instances[instance_key]
                instance.last_used_time = datetime.now()
                instance.use_count += 1
                return instance.converter
            
            # 创建新的转换器实例
            logger.info(f"创建新的转换器实例: {instance_key}")
            start_time = time.time()
            
            try:
                converter_class = self._converter_classes[converter_type]
                
                # 如果提供了file_id，使用新的工作目录配置
                if file_id:
                    # 初始化工作目录配置
                    work_dir_config.initialize()
                    # 创建转换器时传入file_id
                    temp_dir = work_dir_config.create_file_work_dir(file_id)
                    converter = converter_class(temp_dir, file_id)
                else:
                    # 兼容旧版本，为每个实例创建独立的临时目录
                    temp_dir = Path(tempfile.mkdtemp(prefix=f"converter_{instance_key}_"))
                    converter = converter_class(temp_dir)
                
                # 预加载模型（如果需要）
                self._preload_models(converter, method)
                
                # 保存实例信息
                instance = ConverterInstance(
                    converter=converter,
                    created_time=datetime.now(),
                    last_used_time=datetime.now(),
                    use_count=1,
                    temp_dir=temp_dir
                )
                
                self._instances[instance_key] = instance
                
                end_time = time.time()
                logger.info(f"转换器实例创建完成: {instance_key}, 耗时: {end_time - start_time:.3f}秒")
                
                return converter
                
            except Exception as e:
                logger.error(f"创建转换器实例失败: {instance_key}, 错误: {e}")
                raise
    
    def _preload_models(self, converter: BaseConverter, method: Optional[str] = None):
        """预加载模型（针对需要加载模型的转换器）"""
        try:
            if isinstance(converter, PDFConverter):
                self._preload_pdf_models(converter, method)
            elif isinstance(converter, ImageConverter):
                self._preload_ocr_models(converter, method)
            # 其他转换器暂时不需要预加载
                
        except Exception as e:
            logger.warning(f"预加载模型失败: {e}")
    
    def _preload_pdf_models(self, converter: PDFConverter, method: Optional[str] = None):
        """预加载PDF转换器的模型"""
        if method == 'marker' or (method is None and converter.is_dependency_available('marker')):
            try:
                # 预加载marker模型
                from marker.models import load_all_models  # type: ignore
                logger.info("预加载marker模型...")
                start_time = time.time()
                load_all_models()
                end_time = time.time()
                logger.info(f"marker模型加载完成，耗时: {end_time - start_time:.3f}秒")
            except ImportError:
                logger.debug("marker不可用，跳过模型预加载")
            except Exception as e:
                logger.warning(f"预加载marker模型失败: {e}")
    
    def _preload_ocr_models(self, converter: ImageConverter, method: Optional[str] = None):
        """预加载OCR模型"""
        # OCR模型已经在OCRInstanceManager中实现了单例模式
        # 这里可以选择性地触发一次初始化
        pass
    
    def get_instance_info(self) -> Dict[str, Dict[str, Any]]:
        """获取所有实例的信息"""
        info = {}
        for key, instance in self._instances.items():
            info[key] = {
                'created_time': instance.created_time.isoformat(),
                'last_used_time': instance.last_used_time.isoformat(),
                'use_count': instance.use_count,
                'converter_type': instance.converter.__class__.__name__,
                'temp_dir': str(instance.temp_dir)
            }
        return info
    
    def cleanup_instance(self, converter_type: str, method: Optional[str] = None, force_cleanup_temp_dir: bool = False):
        """清理指定的转换器实例"""
        instance_key = f"{converter_type}_{method or 'default'}"
        
        if instance_key in self._instances:
            with self._instance_locks.get(instance_key, threading.Lock()):
                if instance_key in self._instances:
                    instance = self._instances[instance_key]
                    
                    # 检查是否需要清理临时目录
                    should_cleanup_temp = force_cleanup_temp_dir
                    
                    # 如果没有强制清理，检查调试模式
                    if not should_cleanup_temp:
                        # 使用内部调试模式标记，避免import失败
                        should_cleanup_temp = not self._debug_mode
                    
                    # 清理临时目录
                    if should_cleanup_temp and instance.temp_dir and instance.temp_dir.exists():
                        try:
                            import shutil
                            shutil.rmtree(instance.temp_dir)
                            logger.info(f"已清理临时目录: {instance.temp_dir}")
                        except Exception as e:
                            logger.warning(f"清理临时目录失败: {e}")
                    elif instance.temp_dir and instance.temp_dir.exists():
                        logger.info(f"调试模式，保留临时目录: {instance.temp_dir}")
                    
                    # 清理转换器资源
                    if hasattr(instance.converter, 'cleanup'):
                        try:
                            instance.converter.cleanup()
                        except Exception as e:
                            logger.warning(f"清理转换器资源失败: {e}")
                    
                    del self._instances[instance_key]
                    logger.info(f"已清理转换器实例: {instance_key}")
    
    def cleanup_all_instances(self, force_cleanup_temp_dirs: bool = False):
        """清理所有转换器实例"""
        logger.info("开始清理所有转换器实例")
        
        # 检查是否为调试模式
        if self._debug_mode and not force_cleanup_temp_dirs:
            logger.info("调试模式下清理转换器实例，保留临时目录")
        
        with self._global_lock:
            for instance_key in list(self._instances.keys()):
                converter_type, method = instance_key.split('_', 1)
                method = method if method != 'default' else None
                self.cleanup_instance(converter_type, method, force_cleanup_temp_dirs)
        
        logger.info("所有转换器实例已清理")
    
    def restart_instance(self, converter_type: str, method: Optional[str] = None):
        """重启指定的转换器实例（销毁旧实例，创建新实例）"""
        logger.info(f"重启转换器实例: {converter_type}_{method or 'default'}")
        
        # 清理旧实例
        self.cleanup_instance(converter_type, method)
        
        # 获取新实例（会自动创建）
        new_converter = self.get_converter(converter_type, method)
        
        logger.info(f"转换器实例重启完成: {converter_type}_{method or 'default'}")
        return new_converter
    
    def restart_all_instances(self):
        """重启所有转换器实例"""
        logger.info("开始重启所有转换器实例")
        
        # 获取当前实例列表
        current_instances = list(self._instances.keys())
        
        # 清理所有实例
        self.cleanup_all_instances()
        
        # 重新创建实例（延迟创建，在下次使用时创建）
        logger.info("所有转换器实例已重启（延迟创建）")
    
    def get_statistics(self) -> Dict[str, Any]:
        """获取转换器使用统计信息"""
        stats = {
            'total_instances': len(self._instances),
            'instances': {},
            'total_usage': 0
        }
        
        for key, instance in self._instances.items():
            stats['instances'][key] = {
                'use_count': instance.use_count,
                'created_time': instance.created_time.isoformat(),
                'last_used_time': instance.last_used_time.isoformat(),
                'uptime_hours': (datetime.now() - instance.created_time).total_seconds() / 3600
            }
            stats['total_usage'] += instance.use_count
        
        return stats
    
    def __del__(self):
        """析构函数，清理所有资源"""
        try:
            # 检查是否为调试模式，如果是则不清理临时目录
            if self._debug_mode:
                logger.info("调试模式下程序结束，保留所有临时目录")
                # 只清理转换器资源，不删除临时目录
                with self._global_lock:
                    for instance_key in list(self._instances.keys()):
                        if instance_key in self._instances:
                            instance = self._instances[instance_key]
                            # 调试模式下不调用cleanup，避免删除临时目录
                            # 只清理Python对象引用
                            del self._instances[instance_key]
                logger.info("调试模式清理完成，临时目录已保留")
            else:
                self.cleanup_all_instances()
        except Exception as e:
            logger.warning(f"析构时清理资源失败: {e}")

# 全局转换器管理器实例
converter_manager = ConverterManager() 